package com.atguigu.tingshu.album.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.RandomUtil;
import com.atguigu.tingshu.album.mapper.AlbumAttributeValueMapper;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.AlbumStatMapper;
import com.atguigu.tingshu.album.service.AlbumInfoService;
import com.atguigu.tingshu.common.cache.GuiGuCache;
import com.atguigu.tingshu.common.config.redis.RedissonConfig;
import com.atguigu.tingshu.common.constant.KafkaConstant;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.common.service.KafkaService;
import com.atguigu.tingshu.model.album.AlbumAttributeValue;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.AlbumStat;
import com.atguigu.tingshu.query.album.AlbumInfoQuery;
import com.atguigu.tingshu.vo.album.AlbumAttributeValueVo;
import com.atguigu.tingshu.vo.album.AlbumInfoVo;
import com.atguigu.tingshu.vo.album.AlbumListVo;
import com.atguigu.tingshu.vo.album.AlbumStatVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.errorprone.annotations.Var;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.pqc.math.linearalgebra.RandUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class AlbumInfoServiceImpl extends ServiceImpl<AlbumInfoMapper, AlbumInfo> implements AlbumInfoService {

    @Autowired
    private AlbumInfoMapper albumInfoMapper;

    @Autowired
    private AlbumAttributeValueMapper albumAttributeValueMapper;

    @Autowired
    private AlbumStatMapper albumStatMapper;

    @Autowired
    private KafkaService kafkaService;
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RedissonClient redissonClient;


    /**
     * 新增专辑
     * 涉及到的表
     * 1.album_info
     * 2.album_attribute_value
     * 3.album_stat
     *
     * @param userId
     * @param albumInfoVo
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveAlbumInfo(Long userId, AlbumInfoVo albumInfoVo) {

        //拷贝数据
        AlbumInfo albumInfo = BeanUtil.copyProperties(albumInfoVo, AlbumInfo.class);
        //设置用户id
        albumInfo.setUserId(userId);
        //免费试听集数tracks_for_free
        if (SystemConstant.ALBUM_PAY_TYPE_REQUIRE.equals(albumInfo.getPayType())) {
            albumInfo.setTracksForFree(5);
        }
        //审核状态为通过
        albumInfo.setStatus(SystemConstant.ALBUM_STATUS_PASS);

        //* 1.album_info
        albumInfoMapper.insert(albumInfo);
        //获取专辑id
        Long albumInfoId = albumInfo.getId();
        //* 2.album_attribute_value

        //获取专辑属性数据
        List<AlbumAttributeValueVo> attributeValueVoList = albumInfoVo.getAlbumAttributeValueVoList();
        //判断
        if (CollectionUtil.isNotEmpty(attributeValueVoList)) {
            for (AlbumAttributeValueVo albumAttributeValueVo : attributeValueVoList) {
                //转换albumAttributeValue
                AlbumAttributeValue albumAttributeValue = BeanUtil.copyProperties(albumAttributeValueVo,
                        AlbumAttributeValue.class);
                albumAttributeValue.setAlbumId(albumInfoId);
                albumAttributeValueMapper.insert(albumAttributeValue);
            }
        }
        //* 3.album_stat
        this.saveAlbumStat(albumInfoId, SystemConstant.ALBUM_STAT_PLAY);
        this.saveAlbumStat(albumInfoId, SystemConstant.ALBUM_STAT_SUBSCRIBE);
        this.saveAlbumStat(albumInfoId, SystemConstant.ALBUM_STAT_BUY);
        this.saveAlbumStat(albumInfoId, SystemConstant.ALBUM_STAT_COMMENT);
        //发送消息--专辑上架
        kafkaService.sendMessage(KafkaConstant.QUEUE_ALBUM_UPPER, String.valueOf(albumInfo.getId()));

    }

    /**
     * 保存专辑统计信息
     *
     * @param albumInfoId
     * @param albumStatPlay
     */
    @Override
    public void saveAlbumStat(Long albumInfoId, String statType) {

        //创建统计对象
        AlbumStat stat = new AlbumStat();
        stat.setAlbumId(albumInfoId);
        stat.setStatType(statType);
        stat.setStatNum(0);
        albumStatMapper.insert(stat);
    }

    /**
     * 查看当前用户专辑分页列表
     *
     * @param albumListVoPage
     * @param albumInfoQuery
     * @return
     */
    @Override
    public Page<AlbumListVo> findUserAlbumPage(Page<AlbumListVo> albumListVoPage, AlbumInfoQuery albumInfoQuery) {
        return albumInfoMapper.findUserAlbumPage(albumListVoPage, albumInfoQuery);
    }

    /**
     * 根据ID删除专辑
     *
     * @param id
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void removeAlbumInfo(Long id) {

        //删除专辑信息表
        //判断--当前专辑下是否有声音，有，提示不可删除
        AlbumInfo albumInfo = albumInfoMapper.selectById(id);
        //判断’
        if (albumInfo != null && albumInfo.getIncludeTrackCount() > 0) {

            throw new GuiguException(ResultCodeEnum.NOTDELETE);
        }
        //删除
        albumInfoMapper.deleteById(id);
        //删除专辑属性表
        // delete from album_attribute_value where album_id=?
        //创建条件构造器
        albumAttributeValueMapper.delete(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, id));

        //删除专辑统计表信息
        // delete from album_stat where album_id=?
        albumStatMapper.delete(new LambdaQueryWrapper<AlbumStat>().eq(AlbumStat::getAlbumId, id));

        //kafka发送消息--专辑下架
        kafkaService.sendMessage(KafkaConstant.QUEUE_ALBUM_LOWER, String.valueOf(id));
    }

    /**
     * 根据ID查询专辑信息
     *
     * @param id
     * @return
     */
    @Override
    public AlbumInfo getAlbumInfoById(Long id) {
        /**
         * 先采用springdataredis分布式锁，解决缓存击穿问题
         * 根据专辑id查询专辑信息包含得属性列表
         */
        try {
            //1.优先从缓存中获取业务数据
            //1.1再业务数据中构建key
            String dataKey = RedisConstant.ALBUM_INFO_PREFIX + id;
            //1.2查询redis缓存
            AlbumInfo albumInfo = (AlbumInfo) redisTemplate.opsForValue().get(dataKey);
            //1.3命中缓存返回就行
            //1.4未命中缓存就执行分布式锁，避免缓存击穿
            if (albumInfo != null) {
                return albumInfo;
            }
            //2.获取分布式锁
            //2.1构建key
            String lockKey = RedisConstant.ALBUM_INFO_PREFIX + id + RedisConstant.CACHE_LOCK_SUFFIX;
            //2.2创建锁对象
            RLock lock = redissonClient.getLock(lockKey);
            //2.3获取锁
            lock.lock();
            //3.执行业务

            try {
                //3.1再查询一次缓存
                albumInfo = (AlbumInfo) redisTemplate.opsForValue().get(dataKey);
                if (albumInfo != null) {
                    return albumInfo;
                }
                //3.2缓存未命中，在查询数据库
                albumInfo = this.getAlbumInfoFromDB(id);

                //3.3如果数据库是空得话，将空数据存入到缓存中，设置时间为10分钟
                if (albumInfo == null) {
                    redisTemplate.opsForValue().set(dataKey, albumInfo, RedisConstant.ALBUM_TEMPORARY_TIMEOUT,
                            TimeUnit.SECONDS);
                    return albumInfo;
                }
                //3.4查询到到数据空时有值的，将数据存放到缓存中，设置时间为挤出时间+随机时间
                int ttl = RandomUtil.randomInt(500, 3600);
                redisTemplate.opsForValue().set(dataKey, albumInfo, RedisConstant.ALBUM_TIMEOUT + ttl,
                        TimeUnit.SECONDS);
                return albumInfo;
            } finally {
                //释放锁
                lock.unlock();
            }

        } catch (Exception e) {
            log.error("[专辑服务]Redis服务不可用，查询DB：{}", e);
            return this.getAlbumInfoFromDB(id);
        }
    }


    /**
     * 根据专辑ID查询专辑信息包含专辑属性列表
     *
     * @param id
     * @return
     */
    @Override
    @GuiGuCache(prefix = "albumInfo:")
    public AlbumInfo getAlbumInfoFromDB(Long id) {
   /*     //查询专辑信息
        AlbumInfo albumInfo = albumInfoMapper.selectById(id);
        //判断
        if (albumInfo != null) {
            //查询专辑属性信息对象
            //select*from album_attribute_value where album_id=?
            List<AlbumAttributeValue> attributeValueList =
                    albumAttributeValueMapper.selectList(new LambdaQueryWrapper<AlbumAttributeValue>().eq
                    (AlbumAttributeValue::getAlbumId, id));
            albumInfo.setAlbumAttributeValueVoList(attributeValueList);
        }
        return albumInfo;*/

        //1.根据主键查询专辑信息
        AlbumInfo albumInfo = albumInfoMapper.selectById(id);

        //2.根据专辑ID查询专辑属性列表
        LambdaQueryWrapper<AlbumAttributeValue> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AlbumAttributeValue::getAlbumId, id);
        List<AlbumAttributeValue> albumAttributeValues = albumAttributeValueMapper.selectList(queryWrapper);
        albumInfo.setAlbumAttributeValueVoList(albumAttributeValues);
        return albumInfo;
    }

    /**
     * 修改专辑
     *
     * @param id
     * @param albumInfoVo
     */
    @Override
    public void updateAlbumInfo(Long id, AlbumInfoVo albumInfoVo) {

        //获取专辑数据
        AlbumInfo albumInfo = BeanUtil.copyProperties(albumInfoVo, AlbumInfo.class);
        //设置id
        albumInfo.setId(id);
        //修改
        albumInfoMapper.updateById(albumInfo);
        //修改属性 1.删除所有关联的属性  2.重新添加

        albumAttributeValueMapper.delete(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, id));

        //保存新提交的属性
        //获取专辑属性数据
        List<AlbumAttributeValueVo> attributeValueVoList = albumInfoVo.getAlbumAttributeValueVoList();
        //判断
        if (CollectionUtil.isNotEmpty(attributeValueVoList)) {
            for (AlbumAttributeValueVo albumAttributeValueVo : attributeValueVoList) {
                //转换albumAttributeValue
                AlbumAttributeValue albumAttributeValue = BeanUtil.copyProperties(albumAttributeValueVo,
                        AlbumAttributeValue.class);
                albumAttributeValue.setAlbumId(id);

                albumAttributeValueMapper.insert(albumAttributeValue);
            }
        }
        //判读单当前is_open字段的值，0表示下架， 1表示上架
        if ("1".equals(albumInfoVo.getIsOpen())) {
            //专辑上架
            kafkaService.sendMessage(KafkaConstant.QUEUE_ALBUM_UPPER, String.valueOf(id));
        } else {
            //专辑上架
            kafkaService.sendMessage(KafkaConstant.QUEUE_ALBUM_LOWER, String.valueOf(id));
        }
    }

    /**
     * 获取当前用户全部专辑列表
     *
     * @param userId
     * @return
     */
    @Override
    public List<AlbumInfo> findUserAllAlbumList(Long userId) {
        LambdaQueryWrapper<AlbumInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AlbumInfo::getUserId, userId).orderByDesc(AlbumInfo::getId).last("limit 200");
        return albumInfoMapper.selectList(queryWrapper);
    }

    /**
     * 根据当前id获取专辑统计信息
     *
     * @param albumId
     * @return
     */
    @Override
    @GuiGuCache(prefix = "albumInfo:")
    public AlbumStatVo getAlbumStatVo(Long albumId) {
        return albumInfoMapper.getAlbumStatVo(albumId);
    }


}